<?php
/*
对象池模式
创建型设计模式
将一些常用的类实例化后，存放一个对象池类中，让其保持立即可用的状态，降低创建和销毁对象所带来的性能开销，提升性能。
初始一定的对象放入对象池中，要使用时，直接拿来使用，不需要时，放回池子中
*/
spl_autoload_register('autoload');

function autoload($class) 
{
    require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php';
}

/*============================= 测试 =============================*/
use objectpool\ObjectPool;

$worker1 = ObjectPool::get(); //装载一个对象
sleep(1);
$worker2 = ObjectPool::get(); //再次装载一个对象
ObjectPool::see(); //此时有两个对象正在使用中
ObjectPool::dispose($worker1); //把第一个空闲出来
ObjectPool::see(); //此时一个在使用中，一个在空闲
$worker3 = ObjectPool::get(); //再次获取时，会先把空闲的对象给worker3，否则新开一个对象
ObjectPool::see(); //此时又有两个对象正在使用中
echo $worker3->test();
echo $worker2->test();

/*
小结：
对象池模式使用场景：
类的实例化成本高，比如PHP-FPM的进程池、MySQL连接池、使用socket的各种连接池
类的实例化率高

优点：
对象可以重复使用，减少对象的创建与销毁所产生的开销

缺点：
1、在高并发场景中，多个线程同时获取对象池中的对象，会发生锁竞争而产生阻塞，这种开销比创建销毁对象高数百倍
2、对象池能存放的对象数量有限，会带来一个可伸缩性的瓶颈
3、很难正确地设定对象池的大小，如果太小起不到作用，如果太大，则浪费内存资源
4、简单的对象创建池(没有请求外部的资源，仅仅将自身保存在内存中)或许并不会提升效率和性能


参考：https://designpatternsphp.readthedocs.io/zh_CN/latest/Creational/Pool/README.html

扩展学习：
在C语言中，使用malloc函数分配内存，如果分配成功，则返回指向被分配内存空间的指针，失败返回空指针NULL。
同时，当内存不再使用的时候，应使用free()函数将内存块释放掉。
malloc的返回值是一个指针，指向一段可用内存的起始位置，指向一段可用内存的起始地址。
malloc和free是配对的，如果申请后不释放就是内存泄露，如果无故释放那就是什么也没做，
释放只能释放一次，如果一块空间释放两次或者两次以上会出现错误。
malloc分配的内存空间在逻辑上是连续的，而在物理上可以不连续。
作为程序员，关注的是逻辑上的连续，其他的操作系统会帮着我们处理。

*/